 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Configuration;

namespace NetworkSimulator
{
    public class Topology
    {
        // Synchronize object
        public static object lockingObject = new object();

        // SingleTon object
        private static Topology singleTonObject;

        private Config config = Config.instance();

        List<Node> nodes;

        public List<Node> Nodes
        {
            get { return this.nodes; }
        }
        
        List<Link> links;

        public List<Link> Links
        {
            get { return this.links; }
        }

        public static Topology instance()
        {
            lock (lockingObject)
            {
                if (singleTonObject == null)
                {
                    singleTonObject = new Topology();
                }
            }
            return singleTonObject;
        }

        public Topology()
        {
            loadTopologyData();
        }

        public static List<Link> getAllLinks()
        {
            List<Link> result = new List<Link>();

            if (singleTonObject != null)
                foreach (Node node in singleTonObject.nodes)
                {
                    foreach (Link link in node.Links)
                    {
                        result.Add(link);
                    }
                }
            return result;
        }

        private void loadTopologyData()
        {
            FileStream file = new FileStream(config.TopologyFilePath, FileMode.Open);
            StreamReader reader = new StreamReader(file);

            nodes = new List<Node>();

            int n = int.Parse(reader.ReadLine());
            for (int i = 0; i < n; i++)
                nodes.Add(new Node(i));

            while (!reader.EndOfStream)
            {
                string[] value = reader.ReadLine().Split('\t');
                Node nodeA = nodes[int.Parse(value[0])];
                Node nodeB = nodes[int.Parse(value[1])];
                string mode = value[2];
                double capacity = double.Parse(value[3]);

                switch (mode)
                {
                    case "single":
                        {
                            Link link = new Link(nodeA, nodeB, capacity);
                            nodeA.addLink(link);
                            break;
                        }
                    case "double":
                        {
                            Link link = new Link(nodeA, nodeB, capacity);
                            Link rLink = new Link(nodeB, nodeA, capacity);
                            nodeA.addLink(link);
                            nodeB.addLink(rLink);
                            break;
                        }
                }
            }
            file.Close();
        }
    }
}
